home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / DELPHI32 / DISK_UTL / SHOWMAN / FILEINFO.PAS < prev    next >
Pascal/Delphi Source File  |  1996-05-25  |  7KB  |  227 lines

  1. unit FileInfo;
  2.  
  3. interface
  4.  
  5. uses
  6.   Classes;
  7.  
  8. type
  9.   TScanCallback = procedure (const status: string); stdcall;
  10.  
  11.   {forward class declaration}
  12.   TDirectoryData = class;
  13.  
  14.   TDirectoryList = class (TStringList)
  15.   private
  16.     Ftotal_bytes: integer;                // count of bytes here and below
  17.     Ftotal_files: integer;                // count of files here and below
  18.     Ftotal_dirs: integer;                 // count of directories here and below
  19.     Fdirectory_name: string;              // full path specification
  20.     Fparent_directory: TDirectoryList;    // pointer to previous dir, or nil
  21.   public
  22.     constructor Create (const Parent: TDirectoryList;
  23.                         const Name: string);
  24.     procedure SetDirectoryName (const Name: string);
  25.     function GetDirectoryName: string;
  26.     function GetTotalBytes: integer;
  27.     function GetTotalDirectories: integer;
  28.     function GetTotalFiles: integer;
  29.     function GetParentDirectoryList: TDirectoryList;
  30.     procedure scan (var stop_requested: boolean;
  31.                     const cluster_size: integer;
  32.                     Callback: TScanCallback);
  33.   end;
  34.  
  35.   TDirectoryData = class
  36.   private
  37.     Fbytes: integer;
  38.     Fowner_directory: TDirectoryList;   // pointer to current dir list, or nil
  39.     Fsub_directory: TDirectoryList;     // pointer to sub-dir list, or nil
  40.   public
  41.     function GetBytes: integer;
  42.     function GetSubDirectoryList: TDirectoryList;
  43.     function GetParentDirectoryList: TDirectoryList;
  44.     constructor Create (const Size: integer;
  45.                         const OwnerDirectoryList: TDirectoryList;
  46.                         const SubDirectoryList: TDirectoryList);
  47.     destructor Destroy;  override;
  48.   end;
  49.  
  50.  
  51. implementation
  52.  
  53. uses
  54.   SysUtils, Forms;
  55.  
  56. {methods for TDirectoryData}
  57. constructor TDirectoryData.Create (const Size: integer;
  58.                                    const OwnerDirectoryList: TDirectoryList;
  59.                                    const SubDirectoryList: TDirectoryList);
  60. begin
  61.   inherited Create;
  62.   Fowner_directory := OwnerDirectoryList;
  63.   Fsub_directory := SubDirectoryList;
  64.   Fbytes := Size;
  65. end;
  66.  
  67. destructor TDirectoryData.Destroy;
  68. {must dispose of sub-directories as well as main entry}
  69. begin
  70.   if Fsub_directory <> nil then
  71.     begin
  72.     Fsub_directory.Destroy;
  73.     Fsub_directory := nil;
  74.     end;
  75.   Inherited Destroy;
  76. end;
  77.  
  78. function TDirectoryData.GetBytes: integer;
  79. begin
  80.   Result := Fbytes;
  81. end;
  82.  
  83. function TDirectoryData.GetSubDirectoryList: TDirectoryList;
  84. begin
  85.   Result := Fsub_directory;
  86. end;
  87.  
  88. function TDirectoryData.GetParentDirectoryList: TDirectoryList;
  89. begin
  90.   Result := Fowner_directory.GetParentDirectoryList;
  91. end;
  92.  
  93.  
  94. {methods for TDirectoryList}
  95. constructor TDirectoryList.Create (const Parent: TDirectoryList;
  96.                                    const Name: string);
  97. {as standard string list, but allow duplicates, stores name and backlink}
  98. begin
  99.   inherited Create;
  100.   Sorted := False;
  101.   Ftotal_dirs := 0;
  102.   Ftotal_bytes := 0;
  103.   Ftotal_files := 0;
  104.   Fparent_directory := Parent;
  105.   Fdirectory_name := Name;
  106. end;
  107.  
  108. procedure TDirectoryList.SetDirectoryName (const Name: string);
  109. begin
  110.   Clear;
  111.   Fdirectory_name := Name;
  112. end;
  113.  
  114. function TDirectoryList.GetTotalBytes: integer;
  115. begin
  116.   Result := Ftotal_bytes;
  117. end;
  118.  
  119. function TDirectoryList.GetTotalDirectories: integer;
  120. begin
  121.   Result := Ftotal_dirs;
  122. end;
  123.  
  124. function TDirectoryList.GetTotalFiles: integer;
  125. begin
  126.   Result := Ftotal_files;
  127. end;
  128.  
  129. function TDirectoryList.GetParentDirectoryList: TDirectoryList;
  130. begin
  131.   Result := Fparent_directory;
  132. end;
  133.  
  134. function TDirectoryList.GetDirectoryName: string;
  135. begin
  136.   Result := Fdirectory_name;
  137. end;
  138.  
  139. procedure TDirectoryList.scan (var stop_requested: boolean;
  140.                                const cluster_size: integer;
  141.                                Callback: TScanCallback);
  142.  
  143.   function allocated_bytes (file_size, cluster_size: integer): integer;
  144.   var
  145.      fill: integer;
  146.      mask: integer;
  147.   begin
  148.     fill := cluster_size - 1;
  149.     mask := not fill;
  150.     Result := (file_size + fill) and mask;
  151.   end;
  152.  
  153. var
  154.    s: TSearchRec;
  155.    files_to_find: string;
  156.    sub_dir_name: string;
  157.    sub_dir: TDirectoryList;
  158.    next_entry: TDirectoryData;
  159.    bytes_below: integer;
  160.    dirs_below: integer;
  161.    files_below: integer;
  162.    true_size: integer;
  163.    continue: boolean;
  164. begin
  165.   Ftotal_bytes := 0;
  166.   Ftotal_dirs := 0;
  167.   Ftotal_files := 0;
  168.   Callback ('Scanning ' + Fdirectory_name + '...');
  169.   Application.ProcessMessages;
  170.   if FindFirst (Fdirectory_name + '*.*', faAnyFile, s) = 0 then
  171.   repeat
  172.     if stop_requested then Exit;
  173.     with s do
  174.       begin
  175.       if (Attr and faDirectory) <> 0
  176.       then
  177.         begin
  178.         Inc (Ftotal_files);
  179.         // file is sub-directory - but ignore the parent and local backlink
  180.         if (Name = '.') or (Name = '..')
  181.         then
  182.         else
  183.           begin
  184.           Inc (Ftotal_dirs);
  185.           // form new full sub-directory name, with the trailing '\'
  186.           sub_dir_name := Fdirectory_name + Name + '\';
  187.           // allocate a new directory list, insert a record
  188.           // emulating the parent directory
  189.           sub_dir := TDirectoryList.Create (Self, sub_dir_name);
  190.           sub_dir.AddObject ('..', TDirectoryData.Create (0, sub_dir, nil));
  191.           // make the inserted name start with a '\'
  192.           sub_dir_name := '\' + Name;
  193.           // allocate a new entry for the current scan, find out
  194.           // how many bytes and files are in the sub-tree
  195.           next_entry := TDirectoryData.Create (Size, Self, sub_dir);
  196.           with sub_dir do
  197.             begin
  198.             scan (stop_requested, cluster_size, Callback);
  199.             bytes_below := Ftotal_bytes;
  200.             dirs_below := Ftotal_dirs;
  201.             files_below := Ftotal_files;
  202.             // set the size found in this sub-tree and insert the
  203.             // new entry into the current list
  204.             next_entry.Fbytes := bytes_below;
  205.             end;
  206.           AddObject (sub_dir_name, next_entry);
  207.           Inc (Ftotal_bytes, bytes_below);    // bump total bytes found at this
  208.           Inc (Ftotal_dirs, dirs_below);      // (and lower) levels
  209.           Inc (Ftotal_files, files_below);
  210.           end;
  211.         end
  212.       else
  213.         begin
  214.         // for a normal (or hidden) file, insert the name into the list
  215.         true_size := allocated_bytes (Size, cluster_size);
  216.         AddObject (Name, TDirectoryData.Create (true_size, Self, nil));
  217.         Inc (Ftotal_bytes, true_size);
  218.         Inc (Ftotal_files);
  219.         end;
  220.       end;
  221.   until FindNext (s) <> 0;
  222.   FindClose (s);
  223. end;
  224.  
  225. end.
  226.  
  227.